import type { LineEffect, LineEffectType } from '@/types/circuitDiagram'

/**
 * 连线特效工具类
 * 提供特效配置、验证、应用等工具方法
 */
export class LineEffectUtils {
  
  /**
   * 默认特效配置
   */
  static readonly DEFAULT_EFFECT: LineEffect = {
    type: 'current',
    enabled: true,
    color: '#409eff',
    speed: 1000,
    size: 3,
    direction: 'forward',
    intensity: 1,
    opacity: 0.8
  }

  /**
   * 特效类型配置
   */
  static readonly EFFECT_CONFIGS = {
    current: {
      name: '电流',
      description: '模拟电流流动效果',
      defaultColor: '#409eff',
      defaultSpeed: 1000,
      defaultSize: 3
    },
    water: {
      name: '水流',
      description: '模拟水流流动效果',
      defaultColor: '#1890ff',
      defaultSpeed: 1500,
      defaultSize: 4
    },
    arrow: {
      name: '方向',
      description: '带方向指示的箭头',
      defaultColor: '#f56c6c',
      defaultSpeed: 2000,
      defaultSize: 5
    },
    pulse: {
      name: '脉冲',
      description: '脉冲式闪烁效果',
      defaultColor: '#e6a23c',
      defaultSpeed: 800,
      defaultSize: 3
    },
    dash: {
      name: '虚线',
      description: '虚线流动效果',
      defaultColor: '#909399',
      defaultSpeed: 1200,
      defaultSize: 2
    },
    gradient: {
      name: '渐变',
      description: '渐变流动效果',
      defaultColor: '#67c23a',
      defaultSpeed: 1000,
      defaultSize: 3
    }
  }

  /**
   * 验证特效配置
   * @param effect 特效配置
   * @returns 验证结果
   */
  static validateEffect(effect: LineEffect): { valid: boolean; errors: string[] } {
    const errors: string[] = []

    // 检查必需字段
    if (!effect.type) {
      errors.push('特效类型不能为空')
    } else if (!this.EFFECT_CONFIGS[effect.type as LineEffectType]) {
      errors.push('无效的特效类型')
    }

    if (typeof effect.enabled !== 'boolean') {
      errors.push('启用状态必须是布尔值')
    }

    if (!effect.color || !this.isValidColor(effect.color)) {
      errors.push('无效的颜色值')
    }

    if (typeof effect.speed !== 'number' || effect.speed < 100 || effect.speed > 5000) {
      errors.push('速度必须在100-5000毫秒之间')
    }

    if (typeof effect.size !== 'number' || effect.size < 1 || effect.size > 20) {
      errors.push('大小必须在1-20像素之间')
    }

    if (!['forward', 'backward', 'bidirectional'].includes(effect.direction)) {
      errors.push('无效的方向值')
    }

    if (typeof effect.intensity !== 'number' || effect.intensity < 0.1 || effect.intensity > 3) {
      errors.push('强度必须在0.1-3之间')
    }

    if (typeof effect.opacity !== 'number' || effect.opacity < 0.1 || effect.opacity > 1) {
      errors.push('透明度必须在0.1-1之间')
    }

    return {
      valid: errors.length === 0,
      errors
    }
  }

  /**
   * 验证颜色值
   * @param color 颜色值
   * @returns 是否有效
   */
  static isValidColor(color: string): boolean {
    const colorRegex = /^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$|^rgba?\([^)]+\)$|^hsla?\([^)]+\)$/
    return colorRegex.test(color)
  }

  /**
   * 获取特效的默认配置
   * @param type 特效类型
   * @returns 默认配置
   */
  static getDefaultEffect(type: LineEffectType): LineEffect {
    const config = this.EFFECT_CONFIGS[type]
    if (!config) {
      return { ...this.DEFAULT_EFFECT }
    }

    return {
      type,
      enabled: true,
      color: config.defaultColor,
      speed: config.defaultSpeed,
      size: config.defaultSize,
      direction: 'forward',
      intensity: 1,
      opacity: 0.8
    }
  }

  /**
   * 合并特效配置
   * @param base 基础配置
   * @param override 覆盖配置
   * @returns 合并后的配置
   */
  static mergeEffect(base: LineEffect, override: Partial<LineEffect>): LineEffect {
    return {
      ...base,
      ...override
    }
  }

  /**
   * 克隆特效配置
   * @param effect 特效配置
   * @returns 克隆的配置
   */
  static cloneEffect(effect: LineEffect): LineEffect {
    return { ...effect }
  }

  /**
   * 重置特效配置为默认值
   * @param type 特效类型
   * @returns 重置后的配置
   */
  static resetEffect(type: LineEffectType = 'current'): LineEffect {
    return this.getDefaultEffect(type)
  }

  /**
   * 获取特效的CSS动画名称
   * @param effect 特效配置
   * @param elementId 元素ID
   * @returns CSS动画名称
   */
  static getAnimationName(effect: LineEffect, elementId: string): string {
    const baseName = `${effect.type}-${elementId}`
    
    switch (effect.type) {
      case 'current':
        return `current-flow-${elementId}`
      case 'water':
        return `water-flow-${elementId}`
      case 'pulse':
        return `pulse-${elementId}`
      case 'dash':
        return `dash-move-${elementId}`
      case 'gradient':
        return `gradient-flow-${elementId}`
      default:
        return baseName
    }
  }

  /**
   * 获取特效的CSS动画样式
   * @param effect 特效配置
   * @param elementId 元素ID
   * @returns CSS动画样式对象
   */
  static getAnimationStyle(effect: LineEffect, elementId: string): Record<string, string> {
    if (!effect.enabled) {
      return {}
    }

    const animationName = this.getAnimationName(effect, elementId)
    const duration = `${effect.speed}ms`
    
    let direction = 'normal'
    if (effect.direction === 'backward') {
      direction = 'reverse'
    } else if (effect.direction === 'bidirectional') {
      direction = 'alternate'
    }

    return {
      animation: `${animationName} ${duration} linear infinite ${direction}`,
      filter: `blur(${effect.intensity}px)`
    }
  }

  /**
   * 生成特效的CSS动画定义
   * @param effect 特效配置
   * @param elementId 元素ID
   * @returns CSS动画定义字符串
   */
  static generateAnimationCSS(effect: LineEffect, elementId: string): string {
    if (!effect.enabled) {
      return ''
    }

    const animationName = this.getAnimationName(effect, elementId)
    
    switch (effect.type) {
      case 'current':
        return `
          @keyframes ${animationName} {
            0% { stroke-dasharray: 0, 100; stroke-dashoffset: 0; }
            50% { stroke-dasharray: 50, 50; stroke-dashoffset: -25; }
            100% { stroke-dasharray: 100, 0; stroke-dashoffset: -50; }
          }
        `
      case 'water':
        return `
          @keyframes ${animationName} {
            0%, 100% { opacity: 0.3; stroke-dasharray: 0, 100; stroke-dashoffset: 0; }
            50% { opacity: 1; stroke-dasharray: 50, 50; stroke-dashoffset: -25; }
          }
        `
      case 'pulse':
        return `
          @keyframes ${animationName} {
            0%, 100% { opacity: 0.5; stroke-width: 2px; transform: scale(1); }
            50% { opacity: 1; stroke-width: 4px; transform: scale(1.1); }
          }
        `
      case 'dash':
        return `
          @keyframes ${animationName} {
            0% { stroke-dashoffset: 0; }
            100% { stroke-dashoffset: 8; }
          }
        `
      case 'gradient':
        return `
          @keyframes ${animationName} {
            0% { stroke-dasharray: 0, 100; stroke-dashoffset: 0; }
            50% { stroke-dasharray: 50, 50; stroke-dashoffset: -25; }
            100% { stroke-dasharray: 100, 0; stroke-dashoffset: -50; }
          }
        `
      default:
        return ''
    }
  }

  /**
   * 获取特效的SVG渐变定义
   * @param effect 特效配置
   * @param elementId 元素ID
   * @returns SVG渐变定义
   */
  static getGradientDefinition(effect: LineEffect, elementId: string): string {
    if (!effect.enabled) {
      return ''
    }

    switch (effect.type) {
      case 'current':
        return `
          <defs>
            <linearGradient id="current-gradient-${elementId}" x1="0%" y1="0%" x2="100%" y2="0%">
              <stop offset="0%" stop-color="${effect.color}" stop-opacity="0" />
              <stop offset="50%" stop-color="${effect.color}" stop-opacity="${effect.opacity}" />
              <stop offset="100%" stop-color="${effect.color}" stop-opacity="0" />
            </linearGradient>
          </defs>
        `
      case 'water':
        return `
          <defs>
            <linearGradient id="water-gradient-${elementId}" x1="0%" y1="0%" x2="100%" y2="0%">
              <stop offset="0%" stop-color="${effect.color}" stop-opacity="0" />
              <stop offset="30%" stop-color="${effect.color}" stop-opacity="${effect.opacity * 0.5}" />
              <stop offset="70%" stop-color="${effect.color}" stop-opacity="${effect.opacity}" />
              <stop offset="100%" stop-color="${effect.color}" stop-opacity="0" />
            </linearGradient>
          </defs>
        `
      case 'gradient':
        return `
          <defs>
            <linearGradient id="gradient-${elementId}" x1="0%" y1="0%" x2="100%" y2="0%">
              <stop offset="0%" stop-color="${effect.color}" stop-opacity="0" />
              <stop offset="25%" stop-color="${effect.color}" stop-opacity="${effect.opacity * 0.3}" />
              <stop offset="50%" stop-color="${effect.color}" stop-opacity="${effect.opacity}" />
              <stop offset="75%" stop-color="${effect.color}" stop-opacity="${effect.opacity * 0.3}" />
              <stop offset="100%" stop-color="${effect.color}" stop-opacity="0" />
            </linearGradient>
          </defs>
        `
      default:
        return ''
    }
  }

  /**
   * 获取特效的SVG图案定义
   * @param effect 特效配置
   * @param elementId 元素ID
   * @returns SVG图案定义
   */
  static getPatternDefinition(effect: LineEffect, elementId: string): string {
    if (!effect.enabled || effect.type !== 'dash') {
      return ''
    }

    return `
      <defs>
        <pattern id="dash-pattern-${elementId}" patternUnits="userSpaceOnUse" width="8" height="1">
          <rect width="4" height="1" fill="${effect.color}" opacity="${effect.opacity}" />
        </pattern>
      </defs>
    `
  }

  /**
   * 获取特效的SVG标记定义
   * @param effect 特效配置
   * @param elementId 元素ID
   * @returns SVG标记定义
   */
  static getMarkerDefinition(effect: LineEffect, elementId: string): string {
    if (!effect.enabled || effect.type !== 'arrow') {
      return ''
    }

    return `
      <defs>
        <marker id="arrow-${elementId}" markerWidth="10" markerHeight="10" refX="9" refY="3" orient="auto" markerUnits="strokeWidth">
          <path d="M0,0 L0,6 L9,3 z" fill="${effect.color}" opacity="${effect.opacity}" />
        </marker>
      </defs>
    `
  }

  /**
   * 批量应用特效到多个连线
   * @param elements 连线元素数组
   * @param effect 特效配置
   * @returns 更新后的元素数组
   */
  static applyEffectToElements(elements: any[], effect: LineEffect): any[] {
    return elements.map(element => {
      if (element.type === 'line') {
        return {
          ...element,
          lineEffect: this.cloneEffect(effect)
        }
      }
      return element
    })
  }

  /**
   * 检查特效是否支持某个属性
   * @param effectType 特效类型
   * @param property 属性名
   * @returns 是否支持
   */
  static isPropertySupported(effectType: LineEffectType, property: string): boolean {
    const supportedProperties: Record<LineEffectType, string[]> = {
      current: ['color', 'speed', 'size', 'direction', 'intensity', 'opacity'],
      water: ['color', 'speed', 'size', 'direction', 'intensity', 'opacity'],
      arrow: ['color', 'speed', 'size', 'direction', 'opacity'],
      pulse: ['color', 'speed', 'size', 'intensity', 'opacity'],
      dash: ['color', 'speed', 'size', 'direction', 'opacity'],
      gradient: ['color', 'speed', 'size', 'direction', 'intensity', 'opacity']
    }

    return supportedProperties[effectType]?.includes(property) || false
  }

  /**
   * 获取特效的性能等级
   * @param effect 特效配置
   * @returns 性能等级：low, medium, high
   */
  static getPerformanceLevel(effect: LineEffect): 'low' | 'medium' | 'high' {
    if (!effect.enabled) {
      return 'low'
    }

    // 根据特效类型和参数评估性能
    const performanceScores: Record<LineEffectType, number> = {
      current: 2,
      water: 3,
      arrow: 1,
      pulse: 2,
      dash: 2,
      gradient: 3
    }

    const baseScore = performanceScores[effect.type] || 1
    const speedFactor = effect.speed < 500 ? 2 : effect.speed > 2000 ? 0.5 : 1
    const intensityFactor = effect.intensity > 1.5 ? 1.5 : 1

    const totalScore = baseScore * speedFactor * intensityFactor

    if (totalScore <= 1.5) {
      return 'low'
    } else if (totalScore <= 3) {
      return 'medium'
    } else {
      return 'high'
    }
  }
} 